package com.zy.view.handler;

import static com.zy.view.handler.HandlerModelView.Status.DOING;
import static com.zy.view.handler.HandlerModelView.Status.FIND_NODE;
import static com.zy.view.handler.HandlerModelView.Status.MOVE;
import static com.zy.view.handler.HandlerModelView.Status.MOVE_DONE;
import static com.zy.view.handler.HandlerModelView.Status.MOVE_NODE;

import android.animation.Animator;
import android.animation.AnimatorListenerAdapter;
import android.animation.ValueAnimator;
import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.DashPathEffect;
import android.graphics.Paint;
import android.graphics.RectF;
import android.support.annotation.Nullable;
import android.util.AttributeSet;
import android.util.Log;
import android.view.View;
import android.view.animation.LinearInterpolator;

import com.example.thread.ZYThreadUtils;
import com.zy.view.R;

import java.util.ArrayList;
import java.util.List;
import java.util.Random;

public class HandlerModelView extends View {

    private static final String TAG = "HandlerModelView";

    private static final int COMMON = 1;
    private static final int ASYNC = 2;
    private static final int SYNC = 3;


    private static int commonId = 0;
    private static int asyncId = 0;
    private static int syncId = 0;

    public HandlerModelView(Context context) {
        super(context);
        init(context);
    }

    public HandlerModelView(Context context, @Nullable AttributeSet attrs) {
        super(context, attrs);
        init(context);
    }

    public HandlerModelView(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        init(context);
    }

    public HandlerModelView(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) {
        super(context, attrs, defStyleAttr, defStyleRes);
        init(context);
    }

    private List<Integer> pendingTypeList = new ArrayList<>();

    Paint textPaint;
    //辅助线
    Paint assistLinePaint;

    //
    Paint commonMSGPaint;
    Paint commonMSGPaintBack;

    Paint asyncMSGPaint;
    Paint asyncMSGPaintBack;

    Paint syncMSGPaint;
    Paint syncMSGPaintBack;

    Paint finishMSGPaint;
    Paint finishMSGPaintBack;

    Paint doingMSGPaint;
    Paint doingMSGPaintBack;


    private void init(Context context) {

        textPaint = new Paint();
        //设置文本大小
        textPaint.setTextSize(48);
        //设置文本对齐方式
        textPaint.setTextAlign(Paint.Align.CENTER);
        textPaint.setColor(Color.WHITE);


        assistLinePaint = new Paint();
        assistLinePaint.setColor(Color.GRAY);
        assistLinePaint.setStrokeWidth(4);
        DashPathEffect effects = new DashPathEffect(new float[]{10, 10, 10, 10}, 10);
        assistLinePaint.setPathEffect(effects);


        commonMSGPaint = new Paint();
        commonMSGPaint.setColor(Color.BLUE);
        commonMSGPaintBack = new Paint();
        commonMSGPaintBack.setColor(getResources().getColor(R.color.blue_low));

        asyncMSGPaint = new Paint();
        asyncMSGPaint.setColor(Color.YELLOW);
        asyncMSGPaintBack = new Paint();
        asyncMSGPaintBack.setColor(getResources().getColor(R.color.yellow_low));

        syncMSGPaint = new Paint();
        syncMSGPaint.setColor(Color.RED);
        syncMSGPaintBack = new Paint();
        syncMSGPaintBack.setColor(getResources().getColor(R.color.red_low));

        finishMSGPaint = new Paint();
        finishMSGPaint.setColor(Color.GREEN);
        finishMSGPaintBack = new Paint();
        finishMSGPaintBack.setColor(getResources().getColor(R.color.green_low));

        doingMSGPaint = new Paint();
        doingMSGPaint.setColor(getResources().getColor(R.color.purple));
        doingMSGPaintBack = new Paint();
        doingMSGPaintBack.setColor(getResources().getColor(R.color.purple_low));

        initPendingList();
    }


    //辅助信息
    boolean initAssist = false;
    List<MSGNode> assistMsgNodes = new ArrayList<>();

    //数量一直是6个，少了一个就补充
    List<MSGNode> msgNodes = new ArrayList<>();
    List<MSGNode> doneMsgNodes = new ArrayList<>();
    List<MSGNode> drawMsgNodes = new ArrayList<>();


    private static final int NODE_SIZE = 6;

    private void randomBuildNode() {
        while (msgNodes.size() < NODE_SIZE) {
            if (pendingTypeList.size() > 1) {
                addNode(pendingTypeList.remove(0));
            } else {
                Random random = new Random();
                if (hasSyncMsg()) {
                    addNode(random.nextInt(2) + 1);
                } else {
                    addNode(random.nextInt(3) + 1);
                }
            }
        }
    }


    //是否已经存在屏障消息
    private boolean hasSyncMsg() {
        for (MSGNode msgNode : msgNodes) {
            if (msgNode.msgType == SYNC) {
                return true;
            }
        }
        return false;
    }


    private void initPendingList() {
        pendingTypeList.add(COMMON);
        pendingTypeList.add(COMMON);
        pendingTypeList.add(COMMON);

        pendingTypeList.add(ASYNC);
        pendingTypeList.add(ASYNC);
        pendingTypeList.add(ASYNC);

        pendingTypeList.add(COMMON);
        pendingTypeList.add(ASYNC);
        pendingTypeList.add(COMMON);
        pendingTypeList.add(ASYNC);
        pendingTypeList.add(COMMON);
        pendingTypeList.add(ASYNC);


        pendingTypeList.add(SYNC);

        pendingTypeList.add(COMMON);
        pendingTypeList.add(ASYNC);
        pendingTypeList.add(COMMON);
        pendingTypeList.add(ASYNC);
        pendingTypeList.add(COMMON);
        pendingTypeList.add(ASYNC);
        pendingTypeList.add(COMMON);
        pendingTypeList.add(ASYNC);

    }

    public void startTime() {
        initAssistList();
        startNodeTime();
        startDoneTime();
    }

    private void initAssistList() {
        if (initAssist) {
            return;
        }
        initAssist = true;

        float halfH = getHeight() / 2.0f;

        MSGNode msgNode1 = new MSGNode(COMMON, 300, halfH - 300);
        MSGNode msgNode2 = new MSGNode(ASYNC, 300, halfH);
        MSGNode msgNode3 = new MSGNode(SYNC, 300, halfH + 300);
        assistMsgNodes.add(msgNode1);
        assistMsgNodes.add(msgNode2);
        assistMsgNodes.add(msgNode3);
    }

    private void startNodeTime() {
        ZYThreadUtils.mHandler.postDelayed(new Runnable() {
            @Override
            public void run() {
                stepTime();
            }
        }, 20);
    }

    private void startDoneTime() {
        ZYThreadUtils.mHandler.postDelayed(new Runnable() {
            @Override
            public void run() {
                stepDoneTime();
            }
        }, 20);
    }


    private void starNextTime() {
        startNodeTime();
    }


    private void starNextDoneTime() {
        startDoneTime();
    }

    float baseLineStartX = -10;
    float baseNodeStartX = 200;

    int nodeW = 100;
    int nodeH = 80;
    int nodeDoingH = 20;


    @Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);
        //width:2268 height:1104
        //Log.d(TAG, "width:" + getWidth() + " height:" + getHeight()); //width:2499 height:1200
        int centerX = getWidth() / 2;
        int centerY = getHeight() / 2;

//        canvas.clipRect(centerX, 0, getWidth(), getHeight());
//
//        canvas.drawLine(baseLineStartX + 50, centerY - nodeH - 4, baseLineStartX + getWidth() + 10, centerY - nodeH - 4, assistLinePaint);
//        canvas.drawLine(baseLineStartX + 50, centerY + nodeH + 4, baseLineStartX + getWidth() + 10, centerY + nodeH + 4, assistLinePaint);
//
//        drawMSG(canvas, baseNodeStartX + getWidth() + nodeW, centerY);

        drawMsgNodes.clear();
        drawMsgNodes.addAll(msgNodes);
        for (BaseNode msgNode : drawMsgNodes) {
            msgNode.draw(canvas);
        }

        drawMsgNodes.clear();
        drawMsgNodes.addAll(doneMsgNodes);
        canvas.save();
        canvas.clipRect(500, 0, getWidth(), getHeight());
        for (BaseNode msgNode : drawMsgNodes) {
            msgNode.draw(canvas);
        }
        canvas.restore();

        if (mDoingNode != null) {
            mDoingNode.draw(canvas);
        }

        if (moveDone != null) {
            moveDone.draw(canvas);
        }

        //drawTextCenter(canvas, 200, 200, "" + status);

        for (MSGNode assistMsgNode : assistMsgNodes) {
            assistMsgNode.draw(canvas);
        }

        canvas.drawLine(500, 0, 500, getHeight(), assistLinePaint);
    }

    private void stepDoneTime() {
        if (doneMsgNodes.isEmpty()) {
            postInvalidate();
            starNextDoneTime();
            return;
        }
        int base = NODE_SIZE - doneMsgNodes.size();
//        if (base == 0) {
//            base = -1;
//        }
        for (int index = 0; index < doneMsgNodes.size(); index++) {
            MSGNode msgNode = doneMsgNodes.get(index);
            msgNode.stepTime(index, index + 1 + base);
        }

        postInvalidate();
        starNextDoneTime();
    }


    private void stepTime() {
        this.status = MOVE;
        if (msgNodes.size() < NODE_SIZE) {
            randomBuildNode();
        }

        boolean move = false;
        for (int index = 0; index < msgNodes.size(); index++) {
            MSGNode msgNode = msgNodes.get(index);
            if (msgNode.stepTime(index, index + 1)) {
                move = true;
            }
        }


        if (!move) { //本次没有移动,开始处理任务
            handleMsgNodePer(FIND_NODE);
        } else {
            invalidate();
            starNextTime();
        }
    }

    enum Status {
        MOVE, FIND_NODE, MOVE_NODE, DOING, MOVE_DONE,
    }

    private Status status = MOVE;
    private int pendingNodeIndex = -1; //待处理Node 下标
    private int findPendingNodeIndex = -1; //查询下标
    private boolean hasSyncNodeInHead = false; //是否存在同步屏障


    public void handleMsgNodePer(Status status) {
        Log.d(TAG, "handleMsgNodePer status:" + status);
        this.status = status;
        postInvalidate();
        ZYThreadUtils.mHandler.postDelayed(new Runnable() {
            @Override
            public void run() {
                handleMsgNode(status);
            }
        }, 500);
    }

    public void findASyncMsgNodePer(int index) {
        Log.d(TAG, "findASyncMsgNodePer index:" + index);
        postInvalidate();
        ZYThreadUtils.mHandler.postDelayed(new Runnable() {
            @Override
            public void run() {
                findASyncMsgNode(index);
            }
        }, 500);
    }

    private void handleMsgNode(Status status) {
        //找到本次处理的node
        //移动到具体的位置
        //处理中 -> 处理完成
        switch (status) {
            case FIND_NODE:
                //先判断第一个是不是同步屏障
                MSGNode msgNode = msgNodes.get(0);
                if (msgNode.msgType == SYNC) { //队列头部是同步屏障
                    hasSyncNodeInHead = true;
                    findASyncMsgNodePer(1);
                } else { //队列头部不是同步屏障
                    hasSyncNodeInHead = false;
                    pendingNodeIndex = 0;

                    handleMsgNodePer(MOVE_NODE);
                }
                break;
            case MOVE_NODE: {
                moveNode();
            }
            break;
            case DOING: {
                doingNode();
            }
            break;
            case MOVE_DONE: {
                moveDone();
            }
            break;
        }
    }

    //找到第一个异步消息
    private void findASyncMsgNode(int index) {
        if (index >= msgNodes.size()) {
            //没有异步消息-移除屏障
            msgNodes.remove(0);
            findPendingNodeIndex = -1;
            starNextTime();
            return;
        }
        MSGNode msgNode = msgNodes.get(index);
        //Log.d(TAG, "findASyncMsgNode index:" + index + " msgType:" + msgNode.msgType);
        if (msgNode.msgType == ASYNC) {//找到了异步消息
            pendingNodeIndex = index;
            findPendingNodeIndex = -1;
            handleMsgNodePer(MOVE_NODE);
        } else {
            findPendingNodeIndex = index;
            findASyncMsgNodePer(index + 1);
        }
    }

    //移动node到要处理的位置
    private void handleMoveNode(float percent) {
        MSGNode doingNode = msgNodes.get(pendingNodeIndex);
        doingNode.moveNode(percent);
    }

    private void handleNodeDoingStart() {
        MSGNode doingNode = msgNodes.get(pendingNodeIndex);
        doingNode.doingStart();
    }

    //移动到已解决队列
    private void handleMoveDoneNode(float percent) {
        //Log.d(TAG, "handleMoveDoneNode percent:" + percent);
        if (moveDone != null) {
            moveDone.moveDone(percent);
        }
    }

    private void handleMoveDoneEnd() {
        if (moveDone != null) {
            moveDone.setMsgNodeDone();
            doneMsgNodes.add(moveDone);
            moveDone = null;
        }
    }

    MSGNode moveDone;

    private void handleMoveDoneStart() {
        moveDone = msgNodes.remove(pendingNodeIndex);

        starNextTime();
    }


    private void handleNodeDoingEnd() {
        MSGNode doingNode = msgNodes.get(pendingNodeIndex);
        doingNode.doingEnd();

        checkDoingNode();
        mDoingNode.doing(0);
    }

    DoingNode mDoingNode;

    private void checkDoingNode() {
        if (mDoingNode == null) {
            mDoingNode = new DoingNode(0);
        }
    }

    private void handleDoingNode(float percent) {
        checkDoingNode();
        mDoingNode.doing(percent);
    }


    public abstract static class BaseNode {
        abstract void draw(Canvas canvas);
    }

    public class DoingNode {
        private float centerX = 0;//初始
        private float centerY = 0;//初始

        private float percent = 0;

        private static final int DEP = 3;

        private static final int RX = 10;
        private static final int RY = 10;

        public DoingNode(float percent) {
            this.percent = percent;
            this.centerX = getWidth() / 2.0f;
            this.centerY = getHeight() / 2.0F + nodeDoingH + 40;
        }

        public void doing(float percent) {
            this.percent = percent;
        }


        private RectF getCurRectF() {
            return new RectF(centerX - nodeW, centerY - nodeDoingH, centerX + nodeW, centerY + nodeDoingH);
        }

        private RectF getCurRectFContext(float percent) {

            float left = centerX - nodeW + DEP;
            float right = centerX + nodeW - DEP;

            float width = right - left;

            float curWidth = width * percent;


            return new RectF(left, centerY - nodeDoingH + DEP, left + curWidth, centerY + nodeDoingH - DEP);
        }

        public void draw(Canvas canvas) {
            canvas.drawRoundRect(getCurRectF(), RX, RY, doingMSGPaint);
            canvas.drawRoundRect(getCurRectFContext(1), RX, RY, doingMSGPaintBack);
            canvas.drawRoundRect(getCurRectFContext(percent), RX, RY, doingMSGPaint);
        }
    }


    public class MSGNode extends BaseNode {

        //1，2，3
        private int msgType = 1;

        private int id = 0;

        private float centerX = 0;//初始
        private float centerY = 0;//初始

        private int birthdayTime = 0;

        private int handleTime = 0; //随机处理时间（1000-3000）

        private static final int RX = 10;
        private static final int RY = 10;

        private static final int DEP = 10;
        private static final int FACTOR = 10;
        private static final int BASE_LINE_X = 350;
        private static final int PER_LINE_X = 300;

        private float curCenterX;
        private boolean done = false; //是否已处理完成
        private int curIndex = -1;
        private float offsetX = 0;
        private float offsetY = 0;

        private boolean assist = false; //辅助node


        public MSGNode(int msgType) {
            this.msgType = msgType;
            this.centerX = getWidth() + nodeW;
            this.centerY = getHeight() / 5.0F;

            if (msgType == COMMON) {
                id = commonId++;
            } else if (msgType == ASYNC) {
                id = asyncId++;
            } else if (msgType == SYNC) {
                id = syncId++;
            }
        }


        public MSGNode(int msgType, float centerX, float centerY) {
            this.msgType = msgType;
            this.centerX = centerX;
            this.centerY = centerY;
            this.curCenterX = centerX;
            this.assist = true;
        }

        public void moveDone(float percent) {
            float targetX = getWidth() + nodeW - 40;
            float targetY = getHeight() / 5.0F * 4;

            float XD = targetX - curCenterX;
            float YD = targetY - centerY;

            offsetX = percent * XD;
            offsetY = percent * YD;
        }

        public void setMsgNodeDone() {
            //msgType = DONE;
            birthdayTime = 0;
            curCenterX = 0;
            offsetX = 0;
            offsetY = 0;
            this.centerX = getWidth() + nodeW - 40;
            this.centerY = getHeight() / 5.0F * 4;

            done = true;
        }


        private RectF getCurRectF() {
            return new RectF(getCenterX() - nodeW, getCenterY() - nodeH, getCenterX() + nodeW, getCenterY() + nodeH);
        }

        private RectF getDoneRectF() {
            return new RectF(getCenterX() - nodeW - DEP, getCenterY() - nodeH - DEP, getCenterX() + nodeW + DEP, getCenterY() + nodeH + DEP);
        }

        private RectF getPendingRectF() {
            return new RectF(getCenterX() - nodeW - DEP, getCenterY() - nodeH - DEP, getCenterX() + nodeW + DEP, getCenterY() + nodeH + DEP);
        }

        private RectF getCurRectFContext() {
            return new RectF(getCenterX() - nodeW + DEP, getCenterY() - nodeH + DEP, getCenterX() + nodeW - DEP, getCenterY() + nodeH - DEP);
        }

        private float getCenterX() {
            return curCenterX + offsetX;
        }

        private float getCenterY() {
            return centerY + offsetY;
        }


        public void draw(Canvas canvas) {
            canvas.save();
            if (assist) {
                if (msgType == COMMON) {
                    drawCommon(canvas);
                    drawTextCenter(canvas, getCenterX(), getCenterY(), "普通消息");
                } else if (msgType == ASYNC) {
                    drawASyncMSG(canvas);
                    drawTextCenter(canvas, getCenterX(), getCenterY(), "异步消息");
                } else if (msgType == SYNC) {
                    drawSyncMSG(canvas);
                    drawTextCenter(canvas, getCenterX(), getCenterY(), "同步屏障");
                }
            } else {

                if (status == FIND_NODE) {//状态是正在找node
                    if (findPendingNodeIndex == curIndex) {
                        canvas.drawRoundRect(getPendingRectF(), RX, RY, doingMSGPaint);
                    }

                    //屏障消息node
                    if (curIndex == 0 && msgType == SYNC) {
                        canvas.drawRoundRect(getPendingRectF(), RX, RY, doingMSGPaint);
                    }

                } else if (status == MOVE_NODE) {
                    //屏障消息node
                    if (curIndex == 0 && msgType == SYNC) {
                        canvas.drawRoundRect(getPendingRectF(), RX, RY, doingMSGPaint);
                    }

                    if (pendingNodeIndex == curIndex) {
                        canvas.drawRoundRect(getPendingRectF(), RX, RY, doingMSGPaint);
                    }
                } else if (status == DOING) {
                    //屏障消息node
                    if (curIndex == 0 && msgType == SYNC) {
                        canvas.drawRoundRect(getPendingRectF(), RX, RY, doingMSGPaint);
                    }

                    if (pendingNodeIndex == curIndex) {
                        canvas.drawRoundRect(getPendingRectF(), RX, RY, doingMSGPaint);
                    }
                } else if (status == MOVE_DONE) {
                    //屏障消息node
                    if (curIndex == 0 && msgType == SYNC) {
                        canvas.drawRoundRect(getPendingRectF(), RX, RY, doingMSGPaint);
                    }

                    if (pendingNodeIndex == curIndex) {
                        canvas.drawRoundRect(getPendingRectF(), RX, RY, doingMSGPaint);
                    }
                }


                if (done) {
                    canvas.drawRoundRect(getDoneRectF(), RX, RY, finishMSGPaint);
                }

                if (msgType == COMMON) {
                    drawCommon(canvas);
                    drawTextCenter(canvas, getCenterX(), getCenterY(), "普通:" + id);
                } else if (msgType == ASYNC) {
                    drawASyncMSG(canvas);
                    drawTextCenter(canvas, getCenterX(), getCenterY(), "异步:" + id);
                } else if (msgType == SYNC) {
                    drawSyncMSG(canvas);
                    drawTextCenter(canvas, getCenterX(), getCenterY(), "同步:" + id);
                }
            }
            canvas.restore();
        }

        //是否有未确定位置的Node
        private boolean stepTime(int index, int limitX) {
            curIndex = index;
            //计算当前Node的最小X坐标
            //当前node 的最小限度
            int curLineX = limitX * PER_LINE_X + BASE_LINE_X;
            curCenterX = centerX - birthdayTime * FACTOR;
            boolean move = false;
            if (curCenterX < curLineX) {
                curCenterX = curLineX;
            } else {
                move = true;
                birthdayTime++;
            }
            return move;
        }

        public void moveNode(float percent) {
            float targetX = getWidth() / 2.0f;
            float targetY = getHeight() / 2.0f;

            float XD = targetX - curCenterX;
            float YD = targetY - centerY;

            offsetX = percent * XD;
            offsetY = percent * YD;
        }

        public void doingStart() {
            offsetX = 0;
            offsetY = 0;
            centerY = getHeight() / 2.0f;
            centerX = getWidth() / 2.0f;
            curCenterX = centerX;
        }

        public void doingEnd() {

        }

        private void drawCommon(Canvas canvas) {
            canvas.drawRoundRect(getCurRectF(), RX, RY, commonMSGPaint);
            canvas.drawRoundRect(getCurRectFContext(), RX, RY, commonMSGPaintBack);
        }

        private void drawASyncMSG(Canvas canvas) {
            canvas.drawRoundRect(getCurRectF(), RX, RY, asyncMSGPaint);
            canvas.drawRoundRect(getCurRectFContext(), RX, RY, asyncMSGPaintBack);
        }

        private void drawSyncMSG(Canvas canvas) {
            canvas.drawRoundRect(getCurRectF(), RX, RY, syncMSGPaint);
            canvas.drawRoundRect(getCurRectFContext(), RX, RY, syncMSGPaintBack);
        }
    }

    public void addNode(int type) {
        //位置确认,初始
        msgNodes.add(new MSGNode(type));
    }

    public void moveNode() {
        ValueAnimator valueAnimator1 = ValueAnimator.ofFloat(0, 1);
        valueAnimator1.setDuration(1000);
        //valueAnimator1.setRepeatCount(1);
        valueAnimator1.setInterpolator(new LinearInterpolator());
        valueAnimator1.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
            @Override
            public void onAnimationUpdate(ValueAnimator animation) {
                handleMoveNode((float) animation.getAnimatedValue());
                postInvalidate();
            }
        });
        valueAnimator1.addListener(new AnimatorListenerAdapter() {
            @Override
            public void onAnimationEnd(Animator animation, boolean isReverse) {
                super.onAnimationEnd(animation, isReverse);
                //结束,开启doing 操作
                handleMsgNodePer(DOING);
            }
        });
        valueAnimator1.start();
    }

    public void doingNode() {
        ValueAnimator valueAnimator1 = ValueAnimator.ofFloat(0, 1);
        valueAnimator1.setDuration(1000);
        valueAnimator1.setInterpolator(new LinearInterpolator());
        valueAnimator1.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
            @Override
            public void onAnimationUpdate(ValueAnimator animation) {
                handleDoingNode((float) animation.getAnimatedValue());
                postInvalidate();
            }
        });
        valueAnimator1.addListener(new AnimatorListenerAdapter() {
            @Override
            public void onAnimationEnd(Animator animation, boolean isReverse) {
                super.onAnimationEnd(animation, isReverse);
                //结束,开启move done 操作
                handleMsgNodePer(MOVE_DONE);

                handleNodeDoingEnd();
            }

            @Override
            public void onAnimationStart(Animator animation, boolean isReverse) {
                super.onAnimationStart(animation, isReverse);
                handleNodeDoingStart();
            }
        });
        valueAnimator1.start();
    }


    private void moveDone() {
        ValueAnimator valueAnimator1 = ValueAnimator.ofFloat(0, 1);
        valueAnimator1.setDuration(1000);
        valueAnimator1.setInterpolator(new LinearInterpolator());
        valueAnimator1.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
            @Override
            public void onAnimationUpdate(ValueAnimator animation) {
                handleMoveDoneNode((float) animation.getAnimatedValue());
                postInvalidate();
            }
        });
        valueAnimator1.addListener(new AnimatorListenerAdapter() {
            @Override
            public void onAnimationEnd(Animator animation, boolean isReverse) {
                super.onAnimationEnd(animation, isReverse);
                //结束,开启move done 操作
                handleMoveDoneEnd();
            }

            @Override
            public void onAnimationStart(Animator animation, boolean isReverse) {
                super.onAnimationStart(animation, isReverse);
                handleMoveDoneStart();
            }
        });
        valueAnimator1.start();
    }


    private void drawTextCenter(Canvas canvas, float centerX, float centerY, String text) {
        //计算基线坐标
        float baseLineY = getBaseLineY(textPaint, centerY);
        canvas.drawText(text, centerX, baseLineY, textPaint);
    }

    private void drawTextCenter(Canvas canvas, int centerX, int centerY, String text) {
        //计算基线坐标
        float baseLineY = getBaseLineY(textPaint, centerY);
        canvas.drawText(text, centerX, baseLineY, textPaint);
    }


    private float getBaseLineY(Paint textPaint, float centerY) {
        Paint.FontMetrics fontMetrics = textPaint.getFontMetrics();
        return centerY + (fontMetrics.descent - fontMetrics.ascent) / 2 - fontMetrics.descent;
    }

}

    